
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package agen.util;

import java.awt.Font;
import java.util.Vector;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * Agrupa un conjunto de componentes SlideBar de la interfaz de usuario y
 * controla que la sumatoria de un valor especifico. Al desplazar una las otras
 * reaccionan en consecuencia para mantener la suma constante.
 * Se implementa mediante un vector en el
 * @author juan
 */
public class SlideBarGroup {

    private Vector<javax.swing.JSlider> grupo = new Vector<javax.swing.JSlider>();
    private int sumatoria = 100; 
    private boolean cambiandoSliderValues = false;

    public int getSumatoria() {
        return sumatoria;
    }

    public void setSumatoria(int sumatoria) {
        this.sumatoria = sumatoria;
    }

    public SlideBarGroup(javax.swing.JSlider[] slides){
        int sumVal = 0;
        Font font = new Font("arial",Font.PLAIN,10);
        for (JSlider jSlider : slides) {
            jSlider.setMaximum(sumatoria);
            jSlider.setMinimum(0);
            jSlider.setValue(sumatoria/slides.length);
            jSlider.setPaintLabels(true);
            jSlider.setPaintTicks(true);
            jSlider.setMajorTickSpacing(hallarEspacioMayor(jSlider));
            jSlider.setMinorTickSpacing(hallarEspacioMenor(jSlider));
            jSlider.setFont(font);
            
            sumVal += jSlider.getValue();
            addJSlider(jSlider);
        }
        if (sumVal != sumatoria) {
            slides[slides.length - 1].setValue(
                    slides[slides.length - 1].getValue() + sumatoria - sumVal);
        }
    }
    public void addJSlider(javax.swing.JSlider slider) {
        grupo.add(slider);
        final int i = grupo.indexOf(slider);
        slider.addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e) {
                JSlider source = (JSlider) e.getSource();
                if (!source.getValueIsAdjusting()) {
                    checkSum(source);
                }
            }
        });
    }

    private void checkSum(javax.swing.JSlider slider) {
        if (!cambiandoSliderValues) {
            cambiandoSliderValues = true;
            int sum = 0, dif, delta, valorActual;
            JSlider slAux;
            for (JSlider jSlider : grupo) {
                sum += jSlider.getValue();
            }
            dif = sumatoria - sum;

            if (dif != 0) {
                for (int i = grupo.size() - 1; i >= 0; i--) {
                    /* En este caso la recorrida al revez es porque considero
                     * que el ajuste se debe hacer desde el �ltimo elemento hasta
                     * el primero, obviamente salteando el source del evento.
                     */
                    slAux = grupo.get(i);
                    if (!slAux.equals(slider)) {
                        valorActual = slAux.getValue();
                        if (dif > 0) {
                            delta = Math.min(slAux.getMaximum() - valorActual, dif);
                            slAux.setValue(valorActual + delta);
                        } else {
                            delta = Math.max(-(valorActual - slAux.getMinimum()), dif);
                            slAux.setValue(valorActual + delta);
                        }
                        dif -= delta;
                        if (dif == 0) {
                            break;
                        }
                    }
                }
            }
            cambiandoSliderValues = false;
        }

    }

    private int hallarEspacioMayor(JSlider slider) {
        int size = slider.getPreferredSize().width;
        System.out.println("int size = slider.getWidth(): " + size);
        //calculo que una medida cada 30 pixels es lo minimo que
        //queda desente.
        int divisor = size / 30;
        System.out.println("int divisor = size / 30: " + divisor);
        while (slider.getMaximum() % divisor != 0){
            //ojo con los maximos primos.
            divisor--;
        }
        return slider.getMaximum() / divisor;
    }

    private int hallarEspacioMenor(JSlider slider) {
        int size = slider.getPreferredSize().width;
        //calculo que una medida cada 5 pixels es lo minimo que
        //queda desente.
        int majorTickSpacing = slider.getMajorTickSpacing();

        int majorTickSpacingPixels =  size /
                (slider.getMaximum() / majorTickSpacing);
        int divisor = majorTickSpacingPixels / 5;
        System.out.println("int divisor =  (size / majorTickSpacing): " + divisor);
        while (majorTickSpacing % divisor != 0){
            //ojo con los maximos primos.
            divisor--;
        }
        return slider.getMajorTickSpacing() / divisor;
    }
}
